home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / ABUSESRC.ZIP / AbuseSrc / imlib / port / mac / RequestVideo.c < prev    next >
C/C++ Source or Header  |  1996-04-11  |  27KB  |  700 lines

  1. /*------------------------------------------------------------------------------
  2. #
  3. #    MacOS¬ Sample Code
  4. #    
  5. #    Written by: Eric Anderson
  6. #     AppleLink: ERIC3
  7. #     AOL: ERICTHREE
  8. #
  9. #    Display Manager sample code
  10. #
  11. #    RequestVideo
  12. #
  13. #    RequestVideo.c    -    C Code
  14. #
  15. #    Copyright ⌐ 1995 Apple Computer, Inc.
  16. #    All rights reserved.
  17. #
  18. #    5/31/95        ewa        Added RVGetCurrentVideoSetting and RVConfirmVideoRequest routines
  19. #                        to make it easy to revert back to where you came from and to give
  20. #                        the user a chance to confirm the new setting if the new mode was
  21. #                        valid (ie: the card supports it) but not safe (the monitor may not).
  22. #    5/24/95        ewa        Give the kAllValidModesBit requestFlags option for safe only or all
  23. #                        valid resolution timings.
  24. #
  25. #
  26. #
  27. #    Components:    PlayVideo.c            
  28. #                RequestVideo.c        
  29. #                RequestVideo.h        
  30. #                RequestVideo.rsrc        
  31. #
  32. #    RequestVideo demonstrates the usage of the Display Manager introduced
  33. #    with the PowerMacs and integrated into the system under System 7.5. With
  34. #    the RequestVideo sample code library, developers will be able to explore
  35. #    the Display Manager API by changing bit depth and screen resolution on
  36. #    multisync displays on built-in, NuBus, and PCI based video. Display Manager 1.0
  37. #    is built into the Systems included with the first PowerMacs up through System 7.5.
  38. #    Display Manager 2.0 is included with the release of the new PCI based PowerMacs,
  39. #    and will be included in post 7.5 System Software releases. 
  40. #    
  41. #    It is a good idea to reset the screen(s) to the original setting before exit
  42. #    since the call to RVSetVideoAsScreenPrefs() may not do the right thing under
  43. #    Display Manager 1.0 with certain video drivers.
  44. #
  45. #    For information on the use of this sample code, please the documentation in the Read Me file
  46. ------------------------------------------------------------------------------*/
  47.  
  48. #include "RequestVideo.h"
  49.  
  50. // Internal includes
  51. #include <Dialogs.h>
  52. #include <ROMDefs.h>
  53. #include <Devices.h>
  54. #include <Errors.h>
  55. #include <GestaltEqu.h>
  56. #include <Memory.h>
  57. #include <Palettes.h>
  58. #include <Slots.h>
  59. #include <StdIO.h>
  60. #include <Displays.h>
  61.  
  62. #include <stdlib.h>
  63.  
  64. //--------------------------------------------------------------
  65. //
  66. // Internal defines, structs, typedefs, and routine declarations
  67. //
  68. //--------------------------------------------------------------
  69. #define        KMonoDev            0                        // false (handy definitions for gdDevType settings)
  70. #define        kColorDev            1                        // true
  71. #define        char_Enter            0x03                    // for our filter proc
  72. #define        char_Return            0x0D                    //
  73. #define        iRevertItem            1                        // User buttons
  74. #define        iConfirmItem        2                        //
  75. #define        kSecondsToConfirm    8                        // seconds before confirm dialog is taken down
  76. #define        rConfirmSwtchAlrt    2735                    // ID of alert dialog
  77.  
  78. struct DepthInfo {
  79.     VDSwitchInfoRec            depthSwitchInfo;            // This is the switch mode to choose this timing/depth
  80.     VPBlock                    depthVPBlock;                // VPBlock (including size, depth and format)
  81. };
  82. typedef struct DepthInfo DepthInfo;
  83.  
  84. struct ListIteratorDataRec {
  85.     VDTimingInfoRec            displayModeTimingInfo;        // Contains timing flags and such
  86.     unsigned long            depthBlockCount;            // How many depths available for a particular timing
  87.     DepthInfo                *depthBlocks;                // Array of DepthInfo
  88. };
  89. typedef struct ListIteratorDataRec ListIteratorDataRec;
  90.  
  91. void GetRequestTheDM1Way (        VideoRequestRecPtr requestRecPtr,
  92.                                 GDHandle walkDevice);
  93.  
  94. void GetRequestTheDM2Way (        VideoRequestRecPtr requestRecPtr,
  95.                                 GDHandle walkDevice,
  96.                                 DMDisplayModeListIteratorUPP myModeIteratorProc,
  97.                                 DMListIndexType theDisplayModeCount,
  98.                                 DMListType *theDisplayModeList);
  99.  
  100. pascal void ModeListIterator (    void *userData,
  101.                                 DMListIndexType itemIndex,
  102.                                 DMDisplayModeListEntryPtr displaymodeInfo);
  103.  
  104. Boolean FindBestMatch (            VideoRequestRecPtr requestRecPtr,
  105.                                 short bitDepth,
  106.                                 unsigned long horizontal,
  107.                                 unsigned long vertical);
  108.  
  109. void GravitateMonitors (void);
  110.  
  111. pascal Boolean ConfirmAlertFilter (DialogPtr dlg, EventRecord *evt, short *itemHit);
  112.  
  113. //--------------------------------------------------------------
  114. //
  115. // Implementation of sample code
  116. //
  117. //--------------------------------------------------------------
  118. OSErr RVSetVideoRequest (VideoRequestRecPtr requestRecPtr)
  119. {
  120.     GDHandle        aMonitor;
  121.     Boolean            displayMgrPresent;
  122.     unsigned long    displayMgrVersion;
  123.     OSErr            err;
  124.     Boolean            isColor;
  125.     long            value = 0;
  126.  
  127.     Gestalt(gestaltDisplayMgrVers, (long*)&displayMgrVersion);
  128.     Gestalt(gestaltDisplayMgrAttr,&value);
  129.     displayMgrPresent=value&(1<<gestaltDisplayMgrPresent);
  130.     if (displayMgrPresent)
  131.     {
  132.         if (requestRecPtr->displayMode && requestRecPtr->depthMode)
  133.         {
  134.             if (requestRecPtr->availBitDepth == 1)    // Based on avail bit depth, 
  135.                 isColor = KMonoDev;                    // set the device to a mono device, or
  136.             else isColor = kColorDev;                // set the device to a color device
  137.             SetDeviceAttribute(requestRecPtr->screenDevice,gdDevType,isColor);        
  138.             
  139.             // see how many monitors we have, aMonitor will be nil if we have only one.
  140.             aMonitor = DMGetFirstScreenDevice (dmOnlyActiveDisplays);            // get the first guy
  141.             aMonitor = DMGetNextScreenDevice ( aMonitor, dmOnlyActiveDisplays );    // get the next guy
  142.             
  143.             if (nil == aMonitor || displayMgrVersion >= 0x00020000)
  144.             {
  145.                 // only call DMSetDisplayMode if we have one monitor or DM2.0 is installed
  146.                 // since DM1.0 does not automatically gravitate monitors and our gravitate code
  147.                 // is not implemented.
  148.                 err = DMSetDisplayMode(    requestRecPtr->screenDevice,    // GDevice
  149.                         requestRecPtr->displayMode,                        // DM1.0 uses this
  150.                         &requestRecPtr->depthMode,                        // DM1.0 uses this
  151.                         (unsigned long) &(requestRecPtr->switchInfo),    // DM2.0 uses this rather than displayMode/depthMode combo
  152.                         nil);
  153.                 if (noErr == err)
  154.                 {
  155.                     // Do the monitor gravitate here if we are using a version less than DM2.0
  156.                     if (displayMgrVersion < 0x00020000)
  157.                         GravitateMonitors ();
  158.                 }
  159.                 else if (kDMDriverNotDisplayMgrAwareErr == err)
  160.                 {
  161.                     // DM not supported by driver, so all we can do is set the bit depth
  162.                     err = SetDepth (requestRecPtr->screenDevice, requestRecPtr->depthMode, gdDevType, isColor);
  163.                 }
  164.             }
  165.             else
  166.             {
  167.                 // we have more than one monitor and DM1.0 is installed, so all we can do is set the bit depth
  168.                 err = SetDepth (requestRecPtr->screenDevice, requestRecPtr->depthMode, gdDevType, isColor);
  169.             }
  170.             
  171.             return (err);    // we did try to set the request
  172.         }
  173.     }
  174.     return (-1);    // return a generic error
  175. }
  176.  
  177. // This extern should be removed once this function is formally defined in Displays.h
  178. extern pascal OSErr DMUseScreenPrefs(Boolean usePrefs, Handle displayState)
  179.  THREEWORDINLINE(0x303C, 0x03EC, 0xABEB);
  180.  
  181. OSErr RVSetVideoAsScreenPrefs (void)
  182. {
  183.     Handle        displaystate;
  184.     Boolean        displayMgrPresent;
  185.     long        value = 0;
  186.  
  187.     Gestalt(gestaltDisplayMgrAttr,&value);
  188.     displayMgrPresent=value&(1<<gestaltDisplayMgrPresent);
  189.     if (displayMgrPresent)
  190.     {
  191.         DMBeginConfigureDisplays (&displaystate);    // Tell the world it is about to change
  192.         DMUseScreenPrefs (true, displaystate);        // Make the change
  193.         DMEndConfigureDisplays (displaystate);        // Tell the world the change is over
  194.         
  195.         return (noErr);    // we (maybe) set the world back to a known setting
  196.     }
  197.     return (-1);    // return a generic error
  198. }
  199.  
  200. OSErr RVGetCurrentVideoSetting (VideoRequestRecPtr requestRecPtr)
  201. {
  202.     unsigned long        displayMgrVersion;
  203.     OSErr                error = paramErr;
  204.     CntrlParam            pBlock;
  205.     VDSwitchInfoRec        switchInfo;
  206.     AuxDCEHandle        theDCE;
  207.     VDSwitchInfoRec        videoMode;        
  208.  
  209.     requestRecPtr->availBitDepth            = 0;    // init to default - you can do it if it is important to you
  210.     requestRecPtr->availHorizontal            = 0;
  211.     requestRecPtr->availVertical            = 0;
  212.     requestRecPtr->availFlags                = 0;
  213.     requestRecPtr->displayMode                = -1; 
  214.     requestRecPtr->depthMode                = -1;
  215.     requestRecPtr->switchInfo.csMode        = 0;
  216.     requestRecPtr->switchInfo.csData        = 0;
  217.     requestRecPtr->switchInfo.csPage        = 0;
  218.     requestRecPtr->switchInfo.csBaseAddr    = 0;
  219.     requestRecPtr->switchInfo.csReserved    = 0;
  220.     
  221.     Gestalt(gestaltDisplayMgrVers, (long*)&displayMgrVersion);
  222.     if (requestRecPtr->screenDevice)
  223.     {
  224.         if (displayMgrVersion >= 0x00020000)
  225.         {    // get the info the DM 2.0 way
  226.             error = DMGetDisplayMode(requestRecPtr->screenDevice, &switchInfo);
  227.             if (noErr == error)
  228.             {
  229.                 requestRecPtr->depthMode            = switchInfo.csMode;
  230.                 requestRecPtr->displayMode            = switchInfo.csData; 
  231.                 requestRecPtr->switchInfo.csMode    = switchInfo.csMode;
  232.                 requestRecPtr->switchInfo.csData    = switchInfo.csData;
  233.             }
  234.             return (error);    // we (maybe) set the world back to a known setting
  235.         }
  236.         else
  237.         {    // get the info the DM 1.0 way
  238.             videoMode.csMode = -1;        // init to bogus value
  239.             videoMode.csData = -1;        // init to bogus value            
  240.             pBlock.ioNamePtr = nil;
  241.             pBlock.ioCRefNum = (*(requestRecPtr->screenDevice))->gdRefNum;
  242.             pBlock.csCode = cscGetCurMode;
  243.             *(Ptr *)&pBlock.csParam[0] = (Ptr)&videoMode;
  244.                 
  245.             error = PBStatusSync((ParmBlkPtr )&pBlock);    // ask the driver first....since we trust it the most
  246.                 
  247.             if ( noErr == error && ((-1 == videoMode.csMode) || (-1 == videoMode.csData)) )
  248.                 error = statusErr;
  249.             
  250.             if (noErr != error)    // if the driver has no clue fill it videoMode by hand as a last resort
  251.             {    
  252.                 theDCE = (AuxDCEHandle)GetDCtlEntry((*(requestRecPtr->screenDevice))->gdRefNum);
  253.                 
  254.                 if( theDCE )
  255.                 {
  256.                     videoMode.csData = (unsigned char)(*theDCE)->dCtlSlotId; 
  257.                     videoMode.csMode = (*(requestRecPtr->screenDevice))->gdMode;
  258.                     error = noErr;
  259.                 }
  260.             }
  261.             if (noErr == error)    // Set our data
  262.             {
  263.                 requestRecPtr->displayMode            = videoMode.csData; 
  264.                 requestRecPtr->depthMode            = videoMode.csMode;
  265.                 requestRecPtr->switchInfo.csMode    = videoMode.csMode;
  266.                 requestRecPtr->switchInfo.csData    = videoMode.csData;
  267.             }
  268.             return (error);    // we (maybe) set the world back to a known setting
  269.         }
  270.     }
  271.     return (-1);
  272. }
  273.  
  274. pascal Boolean ConfirmAlertFilter(DialogPtr theDialog, EventRecord *theEvent, short *itemHit)
  275. {
  276.     char charCode;
  277.     Boolean enterORreturn;
  278.     Boolean returnValue = false;
  279.  
  280.     if (0 == GetWRefCon(theDialog))
  281.         SetWRefCon (theDialog,TickCount());
  282.     else
  283.     {
  284.         if (GetWRefCon(theDialog) + kSecondsToConfirm * 60 < TickCount())
  285.         {
  286.             returnValue = true;
  287.             theEvent->what = nullEvent;
  288.             *itemHit = 1;
  289.         }
  290.         else
  291.         {
  292.             if (theEvent->what == keyDown)
  293.             {
  294.                 charCode = (char)theEvent->message & charCodeMask;
  295.                 enterORreturn = (charCode == (char)char_Return) || (charCode == (char)char_Enter);
  296.                 if (enterORreturn)
  297.                 {
  298.                     theEvent->what = nullEvent;
  299.                     returnValue = true;
  300.                     *itemHit = iRevertItem;
  301.                     if (enterORreturn && (0 != (theEvent->modifiers & optionKey)))
  302.                     {
  303.                         *itemHit = iConfirmItem;
  304.                     }
  305.                 }
  306.             }
  307.         }
  308.     }
  309.     return (returnValue);
  310. }
  311.  
  312. OSErr RVConfirmVideoRequest (VideoRequestRecPtr requestRecPtr)
  313. {
  314.     short            alertReturn;        // Alert() return value
  315.     ModalFilterUPP    confirmFilterUPP;    // got to have us one of them new fangled UPP thingies
  316.     
  317.     if (requestRecPtr->availFlags & 1<<kModeValidNotSafeBit)
  318.     {    // new mode is valid but not safe, so ask user to confirm
  319.         SetCursor(&qd.arrow);                                        // have to show the arrow
  320.  
  321.         confirmFilterUPP = NewModalFilterProc (ConfirmAlertFilter);    // create a new modal filter proc UPP
  322.         alertReturn = Alert(rConfirmSwtchAlrt, confirmFilterUPP);    // alert the user
  323.         DisposeRoutineDescriptor (confirmFilterUPP);                // of course there is no DisposeModalFilterProc...
  324.         
  325.         if (alertReturn != iConfirmItem)
  326.             return (-1);                            // tell the caller to switch back to a known setting
  327.         else return (noErr);                        // all is well with the new setting, just leave it
  328.     }
  329.     return (noErr);                                    // the mode was safe, so do nothing
  330. }
  331.  
  332.  
  333. OSErr RVRequestVideoSetting (VideoRequestRecPtr requestRecPtr)
  334. {
  335.     Boolean                            displayMgrPresent;
  336.     short                            iCount = 0;                    // just a counter of GDevices we have seen
  337.     DMDisplayModeListIteratorUPP    myModeIteratorProc = nil;    // for DM2.0 searches
  338.     SpBlock                            spBlock;
  339.     Boolean                            suppliedGDevice;    
  340.     DisplayIDType                    theDisplayID;                // for DM2.0 searches
  341.     DMListIndexType                    theDisplayModeCount;        // for DM2.0 searches
  342.     DMListType                        theDisplayModeList;            // for DM2.0 searches
  343.     long                            value = 0;
  344.     GDHandle                        walkDevice = nil;            // for everybody
  345.  
  346.     Gestalt(gestaltDisplayMgrAttr,&value);
  347.     displayMgrPresent=value&(1<<gestaltDisplayMgrPresent);
  348.     displayMgrPresent=displayMgrPresent && (SVersion(&spBlock)==noErr);    // need slot manager
  349.     if (displayMgrPresent)
  350.     {
  351.         // init the needed data before we start
  352.         if (requestRecPtr->screenDevice)                            // user wants a specifc device?
  353.         {
  354.             walkDevice = requestRecPtr->screenDevice;
  355.             suppliedGDevice = true;
  356.         }
  357.         else
  358.         {
  359.             walkDevice = DMGetFirstScreenDevice (dmOnlyActiveDisplays);            // for everybody
  360.             suppliedGDevice = false;
  361.         }
  362.         
  363.         myModeIteratorProc = NewDMDisplayModeListIteratorProc(ModeListIterator);    // for DM2.0 searches
  364.     
  365.         // Note that we are hosed if somebody changes the gdevice list behind our backs while we are iterating....
  366.         // ...now do the loop if we can start
  367.         if( walkDevice && myModeIteratorProc) do // start the search
  368.         {
  369.             iCount++;        // GDevice we are looking at (just a counter)
  370.             if( noErr == DMGetDisplayIDByGDevice( walkDevice, &theDisplayID, false ) )    // DM1.0 does not need this, but it fits in the loop
  371.             {
  372.                 theDisplayModeCount = 0;    // for DM2.0 searches
  373.                 if (noErr == DMNewDisplayModeList(theDisplayID, 0, 0, &theDisplayModeCount, &theDisplayModeList) )
  374.                 {
  375.                     // search NuBus & PCI the new kool way through Display Manager 2.0
  376.                     GetRequestTheDM2Way (requestRecPtr, walkDevice, myModeIteratorProc, theDisplayModeCount, &theDisplayModeList);
  377.                     DMDisposeList(theDisplayModeList);    // now toss the lists for this gdevice and go on to the next one
  378.                 }
  379.                 else
  380.                 {
  381.                     // search NuBus only the old disgusting way through the slot manager
  382.                     GetRequestTheDM1Way (requestRecPtr, walkDevice);
  383.                 }
  384.             }
  385.         } while ( !suppliedGDevice && nil != (walkDevice = DMGetNextScreenDevice ( walkDevice, dmOnlyActiveDisplays )) );    // go until no more gdevices
  386.         if( myModeIteratorProc )
  387.             DisposeRoutineDescriptor(myModeIteratorProc);
  388.         return (noErr);    // we were able to get the look for a match
  389.     }
  390.     return (-1);        // return a generic error
  391. }
  392.  
  393. void GetRequestTheDM1Way (VideoRequestRecPtr requestRecPtr, GDHandle walkDevice)
  394. {
  395.     AuxDCEHandle myAuxDCEHandle;
  396.     unsigned long    depthMode;
  397.     unsigned long    displayMode;
  398.     OSErr            error;
  399.     OSErr            errorEndOfTimings;
  400.     short            height;
  401.     short            jCount = 0;
  402.     Boolean            modeOk;
  403.     SpBlock            spAuxBlock;
  404.     SpBlock            spBlock;
  405.     unsigned long    switchFlags;
  406.     VPBlock            *vpData;
  407.     short            width;
  408.  
  409.     myAuxDCEHandle = (AuxDCEHandle) GetDCtlEntry((**walkDevice).gdRefNum);    
  410.     spBlock.spSlot = (**myAuxDCEHandle).dCtlSlot;
  411.     spBlock.spID = (**myAuxDCEHandle).dCtlSlotId;
  412.     spBlock.spExtDev = (**myAuxDCEHandle).dCtlExtDev;
  413.     spBlock.spHwDev = 0;                                // we are going to get this pup
  414.     spBlock.spParamData = 1<<foneslot;                    // this slot, enabled, and it better be here.
  415.     spBlock.spTBMask = 3;                                // don't have constants for this yet
  416.     errorEndOfTimings = SGetSRsrc(&spBlock);            // get the spDrvrHW so we know the ID of this puppy. This is important
  417.                                                         // since some video cards support more than one display, and the spDrvrHW
  418.                                                         // ID can, and will, be used to differentiate them.
  419.     
  420.     if ( noErr == errorEndOfTimings )
  421.     {
  422.         // reinit the param block for the SGetTypeSRsrc loop, keep the spDrvrHW we just got
  423.         spBlock.spID = 0;                                // start at zero, 
  424.         spBlock.spTBMask = 2;                            // 0b0010 - ignore DrvrSW - why ignore the SW side? Is it not important for video?
  425.         spBlock.spParamData = (1<<fall) + (1<<foneslot) + (1<<fnext);    // 0b0111 - this slot, enabled or disabled, so we even get 640x399 on Blackbird
  426.         spBlock.spCategory=catDisplay;
  427.         spBlock.spCType=typeVideo;
  428.         errorEndOfTimings = SGetTypeSRsrc(&spBlock);    // but only on 7.0 systems, not a problem since we require DM1.0
  429.         
  430.         // now, loop through all the timings for this GDevice
  431.         if ( noErr == errorEndOfTimings ) do
  432.         {
  433.             // now, loop through all possible depth modes for this timing mode
  434.             displayMode = (unsigned char)spBlock.spID;    // "timing mode, ie:resource ref number"
  435.             for (jCount = firstVidMode; jCount<= sixthVidMode; jCount++)
  436.             {
  437.                 depthMode = jCount;        // vid mode
  438.                 error = DMCheckDisplayMode(walkDevice,displayMode,depthMode,&switchFlags,0,&modeOk);
  439.     
  440.                 // only if the mode is safe or we override it with the kAllValidModesBit request flag
  441.                 if (    noErr == error &&
  442.                         modeOk &&
  443.                         (    switchFlags & 1<<kNoSwitchConfirmBit ||
  444.                             requestRecPtr->requestFlags & 1<<kAllValidModesBit
  445.                         )
  446.                     )
  447.                 {
  448.                     // have a good displayMode/depthMode combo - now lets look inside
  449.                     spAuxBlock = spBlock;                // don't ruin the iteration spBlock!!
  450.                     spAuxBlock.spID = depthMode;        // vid mode
  451.                     error=SFindStruct(&spAuxBlock);        // get back a new spsPointer
  452.                     if (noErr == error)                    // keep going if no error╔
  453.                     {
  454.                         spAuxBlock.spID = 0x01;            // mVidParams request
  455.                         error=SGetBlock (&spAuxBlock);    // use the new spPointer and get back...a NewPtr'ed spResult
  456.                         if (noErr == error)                // ╔keep going if no error╔
  457.                         {                                // We have data! lets have a look
  458.                             vpData = (VPBlock*)spAuxBlock.spResult;
  459.                             height = vpData->vpBounds.bottom;    // left and top are usually zero
  460.                             width = vpData->vpBounds.right;
  461.                             
  462.                             if (FindBestMatch (requestRecPtr, vpData->vpPixelSize, vpData->vpBounds.right, vpData->vpBounds.bottom))
  463.                             {
  464.                                 requestRecPtr->screenDevice = walkDevice;
  465.                                 requestRecPtr->availBitDepth = vpData->vpPixelSize;
  466.                                 requestRecPtr->availHorizontal = vpData->vpBounds.right;
  467.                                 requestRecPtr->availVertical = vpData->vpBounds.bottom;
  468.                                 requestRecPtr->displayMode = displayMode;
  469.                                 requestRecPtr->depthMode = depthMode;
  470.                                 requestRecPtr->switchInfo.csMode = depthMode;                // fill in for completeness
  471.                                 requestRecPtr->switchInfo.csData = displayMode;
  472.                                 requestRecPtr->switchInfo.csPage = 0;
  473.                                 requestRecPtr->switchInfo.csBaseAddr = 0;
  474.                                 requestRecPtr->switchInfo.csReserved = 0;
  475.                                 if (switchFlags & 1<<kNoSwitchConfirmBit)
  476.                                     requestRecPtr->availFlags = 0;                            // mode safe
  477.                                 else requestRecPtr->availFlags = 1<<kModeValidNotSafeBit;    // mode valid but not safe, requires user validation of mode switch
  478.                             }
  479.  
  480.                             if (spAuxBlock.spResult) DisposePtr ((Ptr)spAuxBlock.spResult);    // toss this puppy when done
  481.                         }
  482.                     }
  483.                 }
  484.             }
  485.             // go around again, looking for timing modes for this GDevice
  486.             spBlock.spTBMask = 2;        // ignore DrvrSW
  487.             spBlock.spParamData =  (1<<fall) + (1<<foneslot) + (1<<fnext);    // next resource, this slot, whether enabled or disabled
  488.             errorEndOfTimings = SGetTypeSRsrc(&spBlock);    // and get the next timing mode
  489.         } while ( noErr == errorEndOfTimings );    // until the end of this GDevice
  490.     }
  491.  
  492. }
  493.  
  494. pascal void ModeListIterator(void *userData, DMListIndexType, DMDisplayModeListEntryPtr displaymodeInfo)
  495. {
  496.     unsigned long            depthCount;
  497.     short                    iCount;
  498.     ListIteratorDataRec        *myIterateData        = (ListIteratorDataRec*) userData;
  499.     DepthInfo                *myDepthInfo;
  500.     
  501.     // set user data in a round about way
  502.     myIterateData->displayModeTimingInfo        = *displaymodeInfo->displayModeTimingInfo;
  503.     
  504.     // now get the DMDepthInfo info into memory we own
  505.     depthCount = displaymodeInfo->displayModeDepthBlockInfo->depthBlockCount;
  506.     myDepthInfo = (DepthInfo*)NewPtrClear(depthCount * sizeof(DepthInfo));
  507.  
  508.     // set the info for the caller
  509.     myIterateData->depthBlockCount = depthCount;
  510.     myIterateData->depthBlocks = myDepthInfo;
  511.  
  512.     // and fill out all the entries
  513.     if (depthCount) for (iCount=0; iCount < depthCount; iCount++)
  514.     {
  515.         myDepthInfo[iCount].depthSwitchInfo = 
  516.             *displaymodeInfo->displayModeDepthBlockInfo->depthVPBlock[iCount].depthSwitchInfo;
  517.         myDepthInfo[iCount].depthVPBlock = 
  518.             *displaymodeInfo->displayModeDepthBlockInfo->depthVPBlock[iCount].depthVPBlock;
  519.     }
  520. }
  521.  
  522. void GetRequestTheDM2Way (    VideoRequestRecPtr requestRecPtr,
  523.                             GDHandle walkDevice,
  524.                             DMDisplayModeListIteratorUPP myModeIteratorProc,
  525.                             DMListIndexType theDisplayModeCount,
  526.                             DMListType *theDisplayModeList)
  527. {
  528.     short                    jCount;
  529.     short                    kCount;
  530.     ListIteratorDataRec        searchData;
  531.  
  532.     searchData.depthBlocks = nil;
  533.     // get the mode lists for this GDevice
  534.     for (jCount=0; jCount<theDisplayModeCount; jCount++)        // get info on all the resolution timings
  535.     {
  536.         DMGetIndexedDisplayModeFromList(*theDisplayModeList, jCount, 0, myModeIteratorProc, &searchData);
  537.         
  538.         // for all the depths for this resolution timing (mode)...
  539.         if (searchData.depthBlockCount) for (kCount = 0; kCount < searchData.depthBlockCount; kCount++)
  540.         {
  541.             // only if the mode is valid and is safe or we override it with the kAllValidModesBit request flag
  542.             if    (    searchData.displayModeTimingInfo.csTimingFlags & 1<<kModeValid && 
  543.                     (    searchData.displayModeTimingInfo.csTimingFlags & 1<<kModeSafe ||
  544.                         requestRecPtr->requestFlags & 1<<kAllValidModesBit
  545.                     )
  546.                 )
  547.             {
  548.                 if (FindBestMatch (    requestRecPtr,
  549.                                     searchData.depthBlocks[kCount].depthVPBlock.vpPixelSize,
  550.                                     searchData.depthBlocks[kCount].depthVPBlock.vpBounds.right,
  551.                                     searchData.depthBlocks[kCount].depthVPBlock.vpBounds.bottom))
  552.                 {
  553.                     requestRecPtr->screenDevice = walkDevice;
  554.                     requestRecPtr->availBitDepth = searchData.depthBlocks[kCount].depthVPBlock.vpPixelSize;
  555.                     requestRecPtr->availHorizontal = searchData.depthBlocks[kCount].depthVPBlock.vpBounds.right;
  556.                     requestRecPtr->availVertical = searchData.depthBlocks[kCount].depthVPBlock.vpBounds.bottom;
  557.                     
  558.                     // now set the important info for DM to set the display
  559.                     requestRecPtr->depthMode = searchData.depthBlocks[kCount].depthSwitchInfo.csMode;
  560.                     requestRecPtr->displayMode = searchData.depthBlocks[kCount].depthSwitchInfo.csData;
  561.                     requestRecPtr->switchInfo = searchData.depthBlocks[kCount].depthSwitchInfo;
  562.                     if (searchData.displayModeTimingInfo.csTimingFlags & 1<<kModeSafe)
  563.                         requestRecPtr->availFlags = 0;                            // mode safe
  564.                     else requestRecPtr->availFlags = 1<<kModeValidNotSafeBit;    // mode valid but not safe, requires user validation of mode switch
  565.     
  566.                 }
  567.             }
  568.  
  569.         }
  570.     
  571.         if (searchData.depthBlocks)
  572.         {
  573.             DisposePtr ((Ptr)searchData.depthBlocks);    // toss for this timing mode of this gdevice
  574.             searchData.depthBlocks = nil;                // init it just so we know
  575.         }
  576.     }
  577. }
  578.  
  579. Boolean FindBestMatch (VideoRequestRecPtr requestRecPtr, short bitDepth, unsigned long horizontal, unsigned long vertical)
  580. {
  581.     // ÑÑ do the big comparison ÑÑ
  582.     // first time only if    (no mode yet) and
  583.     //                        (bounds are greater/equal or kMaximizeRes not set) and
  584.     //                        (depth is less/equal or kShallowDepth not set) and
  585.     //                        (request match or kAbsoluteRequest not set)
  586.     if    (    nil == requestRecPtr->displayMode
  587.             &&
  588.             (    (horizontal >= requestRecPtr->reqHorizontal &&
  589.                 vertical >= requestRecPtr->reqVertical)
  590.                 ||                                                        
  591.                 !(requestRecPtr->requestFlags & 1<<kMaximizeResBit)    
  592.             )
  593.             &&
  594.             (    bitDepth <= requestRecPtr->reqBitDepth ||    
  595.                 !(requestRecPtr->requestFlags & 1<<kShallowDepthBit)        
  596.             )
  597.             &&
  598.             (    (horizontal == requestRecPtr->reqHorizontal &&    
  599.                 vertical == requestRecPtr->reqVertical &&
  600.                 bitDepth == requestRecPtr->reqBitDepth)
  601.                 ||
  602.                 !(requestRecPtr->requestFlags & 1<<kAbsoluteRequestBit)    
  603.             )
  604.         )
  605.         {
  606.             // go ahead and set the new values
  607.             return (true);
  608.         }
  609.     else    // can we do better than last time?
  610.     {
  611.         // if    (kBitDepthPriority set and avail not equal req) and
  612.         //        ((depth is greater avail and depth is less/equal req) or kShallowDepth not set) and
  613.         //        (avail depth less reqested and new greater avail)
  614.         //        (request match or kAbsoluteRequest not set)
  615.         if    (    (    requestRecPtr->requestFlags & 1<<kBitDepthPriorityBit && 
  616.                     requestRecPtr->availBitDepth != requestRecPtr->reqBitDepth
  617.                 )
  618.                 &&
  619.                 (    (    bitDepth > requestRecPtr->availBitDepth &&
  620.                         bitDepth <= requestRecPtr->reqBitDepth
  621.                     )
  622.                     ||
  623.                     !(requestRecPtr->requestFlags & 1<<kShallowDepthBit)    
  624.                 )
  625.                 &&
  626.                 (    requestRecPtr->availBitDepth < requestRecPtr->reqBitDepth &&
  627.                     bitDepth > requestRecPtr->availBitDepth    
  628.                 )
  629.                 &&
  630.                 (    (horizontal == requestRecPtr->reqHorizontal &&    
  631.                     vertical == requestRecPtr->reqVertical &&
  632.                     bitDepth == requestRecPtr->reqBitDepth)
  633.                     ||
  634.                     !(requestRecPtr->requestFlags & 1<<kAbsoluteRequestBit)    
  635.                 )
  636.             )
  637.         {
  638.             // go ahead and set the new values
  639.             return (true);
  640.         }
  641.         else
  642.         {
  643.             // match resolution: minimize ╞h & ╞v
  644.             if    (    abs((requestRecPtr->reqHorizontal - horizontal)) <=
  645.                     abs((requestRecPtr->reqHorizontal - requestRecPtr->availHorizontal)) &&
  646.                     abs((requestRecPtr->reqVertical - vertical)) <=
  647.                     abs((requestRecPtr->reqVertical - requestRecPtr->availVertical))
  648.                 )
  649.             {
  650.                 // now we have a smaller or equal delta
  651.                 //    if (h or v greater/equal to request or kMaximizeRes not set) 
  652.                 if (    (horizontal >= requestRecPtr->reqHorizontal &&
  653.                         vertical >= requestRecPtr->reqVertical)
  654.                         ||
  655.                         !(requestRecPtr->requestFlags & 1<<kMaximizeResBit)
  656.                     )
  657.                 {
  658.                     // if    (depth is equal or kBitDepthPriority not set) and
  659.                     //        (depth is less/equal or kShallowDepth not set) and
  660.                     //        ([h or v not equal] or [avail depth less reqested and new greater avail] or depth equal avail) and
  661.                     //        (request match or kAbsoluteRequest not set)
  662.                     if    (    (    requestRecPtr->availBitDepth == bitDepth ||            
  663.                                 !(requestRecPtr->requestFlags & 1<<kBitDepthPriorityBit)
  664.                             )
  665.                             &&
  666.                             (    bitDepth <= requestRecPtr->reqBitDepth ||    
  667.                                 !(requestRecPtr->requestFlags & 1<<kShallowDepthBit)        
  668.                             )
  669.                             &&
  670.                             (    (requestRecPtr->availHorizontal != horizontal ||
  671.                                 requestRecPtr->availVertical != vertical)
  672.                                 ||
  673.                                 (requestRecPtr->availBitDepth < requestRecPtr->reqBitDepth &&
  674.                                 bitDepth > requestRecPtr->availBitDepth)
  675.                                 ||
  676.                                 (bitDepth == requestRecPtr->reqBitDepth)
  677.                             )
  678.                             &&
  679.                             (    (horizontal == requestRecPtr->reqHorizontal &&    
  680.                                 vertical == requestRecPtr->reqVertical &&
  681.                                 bitDepth == requestRecPtr->reqBitDepth)
  682.                                 ||
  683.                                 !(requestRecPtr->requestFlags & 1<<kAbsoluteRequestBit)    
  684.                             )
  685.                         )
  686.                     {
  687.                         // go ahead and set the new values
  688.                         return (true);
  689.                     }
  690.                 }
  691.             }
  692.         }
  693.     }
  694.     return (false);
  695. }
  696.  
  697. void GravitateMonitors (void)
  698. {
  699.     // do the magic gravitation here
  700. }